//
//  HKContactManager.m
//  HKAddressBookManager
//
//  Created by 胡锦涛 on 2018/12/27.
//  Copyright © 2018 胡锦涛. All rights reserved.
//

#import "HKContactManager.h"
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#import "HKPerson.h"
#import "HKPeoplePickerDelegate.h"
#import <Contacts/Contacts.h>
#import <ContactsUI/ContactsUI.h>
#import "HKPickerDetailDelegate.h"
#import "NSString+HanExtension.h"

#define HKIOS9 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0)
@interface HKContactManager () <CNContactViewControllerDelegate>

@property (nonatomic, copy) void (^handler) (NSString *, NSString *);
@property (nonatomic, copy) void (^showHandler) (CNContact *);
@property (nonatomic, assign) BOOL isAdd;
@property (nonatomic, copy) NSArray *keys;
@property (nonatomic, strong) HKPeoplePickerDelegate *pickerDelegate;
@property (nonatomic, strong) HKPickerDetailDelegate *pickerDetailDelegate;
@property (nonatomic, strong) CNContactStore *contactStore;
@property (nonatomic) dispatch_queue_t queue;

@end
@implementation HKContactManager

- (instancetype)init
{
    self = [super init];
    if (self)
    {
        _queue = dispatch_queue_create("com.addressBook.queue", DISPATCH_QUEUE_SERIAL);
        if (HKIOS9)
        {
            _contactStore = [CNContactStore new];
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(_contactStoreDidChange)
                                                         name:CNContactStoreDidChangeNotification
                                                       object:nil];
        }
    }
    return self;
}

+ (instancetype)sharedInstance
{
    static id shared_instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shared_instance = [[self alloc] init];
    });
    return shared_instance;
}

- (NSArray *)keys
{
    if (!_keys)
    {
        _keys = @[[CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName],
                  CNContactPhoneNumbersKey,
                  CNContactOrganizationNameKey,
                  CNContactDepartmentNameKey,
                  CNContactJobTitleKey,
                  CNContactNoteKey,
                  CNContactPhoneticGivenNameKey,
                  CNContactPhoneticFamilyNameKey,
                  CNContactPhoneticMiddleNameKey,
                  CNContactImageDataKey,
                  CNContactThumbnailImageDataKey,
                  CNContactEmailAddressesKey,
                  CNContactPostalAddressesKey,
                  CNContactBirthdayKey,
                  CNContactNonGregorianBirthdayKey,
                  CNContactInstantMessageAddressesKey,
                  CNContactSocialProfilesKey,
                  CNContactRelationsKey,
                  CNContactUrlAddressesKey];
        
    }
    return _keys;
}

- (HKPeoplePickerDelegate *)pickerDelegate
{
    if (!_pickerDelegate)
    {
        _pickerDelegate = [HKPeoplePickerDelegate new];
    }
    return _pickerDelegate;
}

- (HKPickerDetailDelegate *)pickerDetailDelegate
{
    if (!_pickerDetailDelegate)
    {
        _pickerDetailDelegate = [HKPickerDetailDelegate new];
        __weak typeof(self) weakSelf = self;
        _pickerDetailDelegate.handler = ^(NSString *name, NSString *phoneNum) {
            NSString *newPhoneNum = [NSString hk_filterSpecialString:phoneNum];
            weakSelf.handler(name, newPhoneNum);
        };
    }
    return _pickerDetailDelegate;
}

/// Return YES if Authorized 返回YES如果得到了授权
- (BOOL)authorizationStatusAuthorized {
    NSInteger status = [self.class authorizationStatus];
    if (status != CNAuthorizationStatusAuthorized) {
        //当某些情况下AuthorizationStatus == AuthorizationStatusNotDetermined时，无法弹出系统首次使用的授权alertView，系统应用设置里亦没有相册的设置，此时将无法使用，故作以下操作，弹出系统首次使用的授权alertView
        [self requestAddressBookAuthorization:nil];
    }
    return status == 3;
}

+ (NSInteger)authorizationStatus {
    if (HKIOS9) {
        CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
        return status;
    }
    return NO;
}

#pragma mark - Public
/*
 [[HKContactManager sharedInstance] selectContactAtController:self complection:^(NSString *name, NSString *phone) {
    self.nameTextField.text = name;
    self.phoneNumTextField.text = phone;
 }];
 */
#pragma mark - Public

- (void)selectContactAtController:(UIViewController *)controller
                      complection:(void (^)(NSString *name, NSString *phone))completcion
{
    self.isAdd = NO;
    [self _presentFromController:controller];
    
    self.handler = completcion;
}

- (void)createNewContactWithPhoneNum:(NSString *)phoneNum controller:(UIViewController *)controller
{
    if (HKIOS9)
    {
        CNMutableContact *contact = [[CNMutableContact alloc] init];
        CNLabeledValue *labelValue = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMobile
                                                                     value:[CNPhoneNumber phoneNumberWithStringValue:phoneNum]];
        contact.phoneNumbers = @[labelValue];
        CNContactViewController *contactController = [CNContactViewController viewControllerForNewContact:contact];
        contactController.delegate = self;
        contactController.contactStore = _contactStore;
        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:contactController];
        [controller presentViewController:nav animated:YES completion:nil];
    }
}
- (void)createNewContactWithPhoneNum:(NSString *)phoneNum withUserName:(NSString *)userName withUserIconName:(NSString *)userIcon complection:(void (^)( CNContact *))completcion
{
    if (HKIOS9)
    {
        CNMutableContact *contact = [[CNMutableContact alloc] init];
        CNLabeledValue *labelValue = [CNLabeledValue labeledValueWithLabel:CNLabelPhoneNumberMobile
                                                                     value:[CNPhoneNumber phoneNumberWithStringValue:phoneNum]];
        contact.phoneNumbers = @[labelValue];
        contact.familyName = userName.length ? userName : @"";
        //@"http://img.zcool.cn/community/01bfde570b50516ac7251f05d1a2c1.gif"
        if (userIcon.length) {
            NSURL *url = [NSURL URLWithString:userIcon];
            NSData *tempData = [NSData dataWithContentsOfURL:url];
            contact.imageData = tempData;
        }else {
            UIImage *originalImage = [UIImage imageNamed:@"default"];
            if (originalImage) {
                contact.imageData = UIImageJPEGRepresentation(originalImage, 1);
            }
        }
        
        
        //添加联系人
        CNSaveRequest * save = [[CNSaveRequest alloc]init];
        [save addContact:contact toContainerWithIdentifier:nil];
        [_contactStore executeSaveRequest:save error:nil];
        completcion(contact);
    }
}

- (void)addToExistingContactsWithPhoneNum:(NSString *)phoneNum controller:(UIViewController *)controller
{
    self.isAdd = YES;
    self.pickerDelegate.phoneNum = phoneNum;
    self.pickerDelegate.controller = controller;
    [self _presentFromController:controller];
}

- (void)setExistingContactsWithUserIconName:(NSString*)userIcon userName:(NSString *)userName withContact:(CNContact *)contact complection:(void (^)( CNContact *))completcion
{
    [self.pickerDelegate setExistingContactsWithUserIcon:userIcon userName:userName contact:contact complection:^(CNContact *contact) {
        completcion(contact);
    }];
}

- (void)deleteContactsWithContact:(CNMutableContact *)contact complection:(void (^)( CNContact *))completcion
{
    // 创建联系人请求
    CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
    [saveRequest deleteContact:contact];
    // 写入操作
    CNContactStore *store = [[CNContactStore alloc] init];
    [store executeSaveRequest:saveRequest error:nil];
    completcion(contact);
}
/*
 [[HKContactManager sharedInstance] accessContactsComplection:^(BOOL succeed, NSArray *datas) {
 
    for (HKPerson *person in datas)
    {
    NSLog(@"名字列表：fullName = %@, firstName = %@, lastName = %@", person.fullName, person.familyName, person.givenName);

    for (HKPhone *model in person.phones)
    {
    NSLog(@"号码：phone = %@, label = %@", model.phone,model.label);
    }

    for (HKEmail *model in person.emails)
    {
    NSLog(@"电子邮件：email = %@, label = %@", model.email, model.label);
    }

    for (HKAddress *model in person.addresses)
    {
    NSLog(@"地址：address = %@, label = %@", model.city, model.label);
    }
    for (HKMessage *model in person.messages)
    {
    NSLog(@"即时通讯：service = %@, userName = %@", model.service, model.userName);
    }

    NSLog(@"生日：brithdayDate = %@",person.birthday.brithdayDate);

    for (HKSocialProfile *model in person.socials)
    {
    NSLog(@"社交：service = %@, username = %@, urlString = %@", model.service, model.username, model.urlString);
    }

    for (HKContactRelation *model in person.relations)
    {
    NSLog(@"关联人：label = %@, name = %@", model.label, model.name);
    }

    for (HKUrlAddress *model in person.urls)
    {
    NSLog(@"URL：label = %@, urlString = %@", model.label,model.urlString);
    }

    NSLog(@"---------------------*******------------------------------------");
    }
 }];
 */
- (void)accessContactsComplection:(void (^)(BOOL, NSArray<HKPerson *> *))completcion
{
    [self requestAddressBookAuthorization:^(BOOL authorization) {
        
        if (authorization)
        {
            if (HKIOS9)
            {
                [self _asynAccessContactStoreWithSort:NO completcion:^(NSArray *datas, NSArray *keys) {
                    
                    if (completcion)
                    {
                        completcion(YES, datas);
                    }
                }];
            }
        }
        else
        {
            if (completcion)
            {
                completcion(NO, nil);
            }
        }
    }];
    
}

/*
 [[HKContactManager sharedInstance] accessSectionContactsComplection:^(BOOL succeed, NSArray<HKSectionPerson *> *contacts, NSArray<NSString *> *keys) {
 
     self.dataSource = contacts;
     self.keys = keys;
     [self.tableView reloadData];
 
     for (HKSectionPerson *sectionModel in contacts)
     {
     NSLog(@"---------------------***%@***------------------------------------",sectionModel.key);
 
     for (HKPerson *person in sectionModel.persons)
     {
     NSLog(@"名字列表：fullName = %@, firstName = %@, lastName = %@", person.fullName, person.familyName, person.givenName);
 
     for (HKPhone *model in person.phones)
     {
     NSLog(@"号码：phone = %@, label = %@", model.phone,model.label);
     }
 
     for (HKEmail *model in person.emails)
     {
     NSLog(@"电子邮件：email = %@, label = %@", model.email, model.label);
     }
 
     for (HKAddress *model in person.addresses)
     {
     NSLog(@"地址：address = %@, label = %@", model.city, model.label);
     }
     for (HKMessage *model in person.messages)
     {
     NSLog(@"即时通讯：service = %@, userName = %@", model.service, model.userName);
     }
 
     NSLog(@"生日：brithdayDate = %@",person.birthday.brithdayDate);
 
     for (HKSocialProfile *model in person.socials)
     {
     NSLog(@"社交：service = %@, username = %@, urlString = %@", model.service, model.username, model.urlString);
     }
 
     for (HKContactRelation *model in person.relations)
     {
     NSLog(@"关联人：label = %@, name = %@", model.label, model.name);
     }
 
     for (HKUrlAddress *model in person.urls)
     {
     NSLog(@"URL：label = %@, urlString = %@", model.label,model.urlString);
     }
 
     }
     }
 
 }];
 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
 {
    return self.dataSource.count;
 }
 
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 {
     HKSectionPerson *sectionModel = self.dataSource[section];
     return sectionModel.persons.count;
 }
 
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
     ContactTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SectionCell"];
     HKSectionPerson *sectionModel = self.dataSource[indexPath.section];
     HKPerson *personModel = sectionModel.persons[indexPath.row];
     cell.model = personModel;
     return cell;
 }
 
 - (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView
 {
    return self.keys;
 }
 
 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
 {
    return 30;
 }
 
 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
 {
     HKSectionPerson *sectionModel = self.dataSource[section];
     return sectionModel.key;
 }
 */
- (void)accessSectionContactsComplection:(void (^)(BOOL, NSArray<HKSectionPerson *> *, NSArray<NSString *> *))completcion
{
    [self requestAddressBookAuthorization:^(BOOL authorization) {
        
        if (authorization)
        {
            if (HKIOS9)
            {
                [self _asynAccessContactStoreWithSort:YES completcion:^(NSArray *datas, NSArray *keys) {
                    
                    if (completcion)
                    {
                        completcion(YES, datas, keys);
                    }
                }];
            }
        }
        else
        {
            if (completcion)
            {
                completcion(NO, nil, nil);
            }
        }
    }];
}

- (void)getPhoneNums:(void (^)(NSMutableArray *nums))completcion {
    [[HKContactManager sharedInstance] requestAddressBookAuthorization:^(BOOL authorization) {
        if (authorization) {
            __weak typeof(self) weakSelf = self;
            [[HKContactManager sharedInstance] accessContactsComplection:^(BOOL succeed, NSArray *datas) {
                __strong typeof(weakSelf) self = weakSelf;
                NSMutableArray * temps = @[].mutableCopy;
                for (HKPerson *person in datas)
                {
                    for (NSString * num in person.mdns) {
                        [temps addObject:num];
                    }
                }
                self.mdns = temps;
                completcion(self.mdns);
            }];
        }else {
            //NSLog(@"未授权");
            [[HKContactManager sharedInstance] showAlert];
        }
    }];
}

- (void)getNameAndNums:(void (^)(NSMutableArray *params))completcion {
    [[HKContactManager sharedInstance] requestAddressBookAuthorization:^(BOOL authorization) {
        if (authorization) {
            __weak typeof(self) weakSelf = self;
            [[HKContactManager sharedInstance] accessContactsComplection:^(BOOL succeed, NSArray *datas) {
                __strong typeof(weakSelf) self = weakSelf;
                NSMutableArray * temps = @[].mutableCopy;
                for (HKPerson *person in datas)
                {
                    NSMutableDictionary * dic = @{@"name":person.fullName,
                                                  @"phoneNums":person.mdns
                                                  }.mutableCopy;
                    [temps addObject:dic];
                }
                self.mdns = temps;
                completcion(self.mdns);
            }];
        }else {
            //NSLog(@"未授权");
            [[HKContactManager sharedInstance] showAlert];
        }
    }];
}

- (void)getNumsAndUniqueIdentifier:(void (^)(NSMutableArray *params))completcion {
    [[HKContactManager sharedInstance] requestAddressBookAuthorization:^(BOOL authorization) {
        if (authorization) {
            __weak typeof(self) weakSelf = self;
            [[HKContactManager sharedInstance] accessContactsComplection:^(BOOL succeed, NSArray *datas) {
                __strong typeof(weakSelf) self = weakSelf;
                NSMutableArray * temps = @[].mutableCopy;
                for (HKPerson *person in datas)
                {
                    NSMutableDictionary * dic = @{@"callToken":person.currentContact.identifier,
                                                  @"callPhones":person.mdns
                                                  }.mutableCopy;
                    [temps addObject:dic];
                }
                self.mdns = temps;
                completcion(self.mdns);
                
            }];
        }else {
            //NSLog(@"未授权");
            [[HKContactManager sharedInstance] showAlert];
        }
    }];
}
#pragma mark - CNContactViewControllerDelegate
- (void)contactViewController:(CNContactViewController *)viewController didCompleteWithContact:(nullable CNContact *)contact
{
    [viewController dismissViewControllerAnimated:YES completion:nil];
}

- (void)requestAddressBookAuthorization:(void (^)(BOOL authorization))completion
{
    if (HKIOS9)
    {
        CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
        
        if (status == CNAuthorizationStatusNotDetermined)
        {
            [_contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
                if (completion)
                {
                    completion(granted);
                }
            }];
        }
        else
        {
            _blockExecute(completion, status == CNAuthorizationStatusAuthorized);
        }
    }
}

#pragma mark - Private
- (void)_authorizationAddressBook:(void (^) (BOOL succeed))completion
{
    if (HKIOS9)
    {
        [_contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (completion)
            {
                completion(granted);
            }
        }];
    }
}

void _blockExecute(void (^completion)(BOOL authorizationA), BOOL authorizationB)
{
    if (completion)
    {
        if ([NSThread isMainThread])
        {
            completion(authorizationB);
        }
        else
        {
            dispatch_async(dispatch_get_main_queue(), ^{
                completion(authorizationB);
            });
        }
    }
}

- (void)_presentFromController:(UIViewController *)controller
{
    if (HKIOS9)
    {
        CNContactPickerViewController *pc = [[CNContactPickerViewController alloc] init];
        if (self.isAdd)
        {
            pc.delegate = self.pickerDelegate;
        }
        else
        {
            pc.delegate = self.pickerDetailDelegate;
        }
        
        pc.displayedPropertyKeys = @[CNContactPhoneNumbersKey];
        
        [self requestAddressBookAuthorization:^(BOOL authorization) {
            if (authorization)
            {
                [controller presentViewController:pc animated:YES completion:nil];
            }
            else
            {
                [self showAlert];
            }
        }];
    }
}

- (void)showAlert
{
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"温馨提示"
                                                        message:@"您的通讯录暂未允许访问，请去设置->隐私里面授权!"
                                                       delegate:nil
                                              cancelButtonTitle:@"确定"
                                              otherButtonTitles:nil, nil];
    [alertView show];
//    [HKAlertView showWithTitle:@"温馨提示" andMessage:@"您的通讯录暂未允许访问，请去设置->隐私里面授权!" cancelTitle:@"取消" cancelHandler:nil ensureTitle:@"确定" ensureHandler:^(HKAlertView *alertView) {
//        NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
//        if([[UIApplication sharedApplication] canOpenURL:url]) {
//            NSURL*url =[NSURL URLWithString:UIApplicationOpenSettingsURLString];
//            //此处可以做一下版本适配，至于为何要做版本适配，大家应该很清楚
//            [[UIApplication sharedApplication] openURL:url];
//        }
//    }];
}

- (void)_asynAccessContactStoreWithSort:(BOOL)isSort completcion:(void (^)(NSArray *, NSArray *))completcion
{
    dispatch_async(_queue, ^{
        
        NSMutableArray *datas = [NSMutableArray array];
        CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:self.keys];
        [self->_contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
            HKPerson *person = [[HKPerson alloc] initWithCNContact:contact];
            [datas addObject:person];
        }];
        
        if (!isSort)
        {
            dispatch_async(dispatch_get_main_queue(), ^{
                
                if (completcion)
                {
                    completcion(datas, nil);
                }
                
            });
            
            return ;
        }
        
        [self _sortNameWithDatas:datas completcion:^(NSArray *persons, NSArray *keys) {
            
            dispatch_async(dispatch_get_main_queue(), ^{
                
                if (completcion)
                {
                    completcion(persons, keys);
                }
                
            });
            
        }];
        
    });
}

- (void)_sortNameWithDatas:(NSArray *)datas completcion:(void (^)(NSArray *, NSArray *))completcion
{
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    
    for (HKPerson *person in datas)
    {
        NSString *firstLetter = [self _firstCharacterWithString:person.fullName];
        
        if (dict[firstLetter])
        {
            [dict[firstLetter] addObject:person];
        }
        else
        {
            NSMutableArray *arr = [NSMutableArray arrayWithObjects:person, nil];
            [dict setValue:arr forKey:firstLetter];
        }
    }
    
    NSMutableArray *keys = [[[dict allKeys] sortedArrayUsingSelector:@selector(compare:)] mutableCopy];
    
    if ([keys.firstObject isEqualToString:@"#"])
    {
        [keys addObject:keys.firstObject];
        [keys removeObjectAtIndex:0];
    }
    
    NSMutableArray *persons = [NSMutableArray array];
    
    [keys enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL * _Nonnull stop) {
        
        HKSectionPerson *person = [HKSectionPerson new];
        person.key = key;
        person.persons = dict[key];
        
        [persons addObject:person];
    }];
    
    if (completcion)
    {
        completcion(persons, keys);
    }
}

- (NSString *)_firstCharacterWithString:(NSString *)string
{
    if (string.length == 0)
    {
        return @"#";
    }
    
    NSMutableString *mutableString = [NSMutableString stringWithString:string];
    
    CFStringTransform((CFMutableStringRef)mutableString, NULL, kCFStringTransformToLatin, false);
    
    NSMutableString *pinyinString = [[mutableString stringByFoldingWithOptions:NSDiacriticInsensitiveSearch locale:[NSLocale currentLocale]] mutableCopy];
    NSString *str = [string substringToIndex:1];
    
    // 多音字处理http://blog.csdn.net/qq_29307685/article/details/51532147
    if ([str isEqualToString:@"长"])
    {
        [pinyinString replaceCharactersInRange:NSMakeRange(0, 5) withString:@"chang"];
    }
    if ([str isEqualToString:@"沈"])
    {
        [pinyinString replaceCharactersInRange:NSMakeRange(0, 4) withString:@"shen"];
    }
    if ([str isEqualToString:@"厦"])
    {
        [pinyinString replaceCharactersInRange:NSMakeRange(0, 3) withString:@"xia"];
    }
    if ([str isEqualToString:@"地"])
    {
        [pinyinString replaceCharactersInRange:NSMakeRange(0, 2) withString:@"di"];
    }
    if ([str isEqualToString:@"重"])
    {
        [pinyinString replaceCharactersInRange:NSMakeRange(0, 5) withString:@"chong"];
    }
    
    NSString *upperStr = [[pinyinString substringToIndex:1] uppercaseString];
    
    NSString *regex = @"^[A-Z]$";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    
    NSString *firstCharacter = [predicate evaluateWithObject:upperStr] ? upperStr : @"#";
    
    return firstCharacter;
}
- (void)_contactStoreDidChange
{
    if ([HKContactManager sharedInstance].contactChangeHandler)
    {
        [HKContactManager sharedInstance].contactChangeHandler();
    }
}

- (void)dealloc
{
    if (HKIOS9)
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:CNContactStoreDidChangeNotification object:nil];
    }
}
@end
